<?php
/**
 * Created by PhpStorm.
 * User: 11893
 * Date: 2018/10/27
 * Time: 11:45
 */

namespace App\Services;


use App\Exceptions\InternalException;
use App\Exceptions\InvalidRequestException;
use App\Jobs\SecKillOrderJob;
use App\Models\Activity;
use App\Models\UserAddress;
use Carbon\Carbon;


class SecKillService
{

    /**
     * Notes:
     * Time: 2018/11/12 14:39
     * @author: Wangguilin
     * @param Activity $activity
     * @throws InternalException
     */
    public function addPlan(Activity $activity)
    {
        $product = $activity->product;
        if (!$product) {
            throw new InternalException('无关联商品');
        }
        $expire = Carbon::parse($activity->end_time)->diffInMinutes();
        $redis = app('redis');
        foreach ($product->skus as $sku) {
            $key = "activity:activity_{$activity->id}_{$sku->id}";
            $redis->set($key, $activity->quantity, $expire*60 + 10);
        }
    }

    /**
     * Notes:
     * Time: 2018/11/12 14:39
     * @author: Wangguilin
     * @param $activity_id
     * @param $sku_id
     * @param $user
     * @throws InvalidRequestException
     */
    public function preOrder($activity_id, $sku_id, $user)
    {
        $key = "activity:activity_{$activity_id}_{$sku_id}";
        $queueKey = "activity:queue_{$activity_id}";

        if ($this->checkUser($queueKey, $user->id)) {
            throw new InvalidRequestException("你已抢购");
        }
//        $result = $this->doSecKill($key, $queueKey, $user->id, $sku_id);
//        dd($result);
        if ($this->doSecKill($key, $queueKey, $user->id, $sku_id) != 1) {
            throw new InvalidRequestException('已抢完');
        }
//        dispatch((new SecKillOrderJob($user, $sku_id, $activity_id))->onQueue('pre-order'));
        $address = UserAddress::first();
        $items = array(
          array(
              'sku_id'=> $sku_id,
              'amount'=> 1,
              'price' => 100
          )
        );
        (new OrderService())->store($user, $address, 'seckill', $items, null, $activity_id );
    }
    protected function checkUser($key, $user)
    {
        $redis = app('redis');
        $script = <<<LUA
        return redis.call('HEXISTS',KEYS[1],ARGV[1])             
LUA;
        return $redis->eval($script, 1, $key, $user);
    }
    protected function doSecKill($key,$queueKey, $user, $sku_id)
    {
        $script = <<<LUA
            local stock = redis.call('get', 'stock')
            if stock == false or tonumber(stock) == 0 then
                return 2
            end 
            redis.call('DECRBY', 'stock', 1)
            if redis.call('HSET', KEYS[2], ARGV[1], ARGV[2]) then
                return 1
            else 
                return 0
            end
LUA;
        return app('redis')->eval($script, 2, $key, $queueKey, $user, $sku_id);
    }


}